package org.su.generalmvc.util;

import org.su.generalmvc.annotaion.Param;
import javassist.*;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;


/**
 * 获取指定方法的参数名称
 * 
 * @author yangchuan CreateTime 2010-7-29 上午09:20:36
 * 
 */
public class ReflectUtils {
	protected static final Log logger = LogFactory.getLog(ReflectUtils.class);
	private static String msg = "class:{} 不包含局部变量表信息，请使用编译器选项 javac -g:{vars}来编译源文件。";
	private static ClassPool pool = ClassPool.getDefault();

	static {
		//指定类扫描位置
		pool.appendClassPath(new LoaderClassPath(ClassUtils
				.getDefaultClassLoader()));
	}
	
	public static void getFileds(Class<?> clazz) {
		try {
			
			CtClass cc = pool.get(clazz.getName());
			CtField[] cfs=cc.getDeclaredFields();
			for(CtField cf:cfs){
				CtClass cc1 = cf.getType();
				
				
					try {
						System.out.print(cc1.toClass()); //得到原始类
					} catch (CannotCompileException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				
				System.out.print("/");
				System.out.print(cf.getName()+"/"); //得到字段名称
				try {
					System.out.println(cf.getAnnotation(Param.class));
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		    System.out.println();
		} catch (NotFoundException e) {
			throw new ParamFoundException(clazz.getName());
		}
	}

	
	/**
	 * 获取方法的参数名称
	 * 
	 * @param clazz
	 *            方法对应的类
	 * @param method
	 *            方法名称
	 * @return 返回参数名称列表（次序为参数定义次序）
	 * @throws NotFoundException
	 *             当类，方法，参数列表（编译在类文件中的局部变量）不存在时抛出。
	 */
	public static String[] getMethodParamNames(Class<?> clazz, String method) {
		try {
			CtClass cc = pool.get(clazz.getName());
			CtMethod cm = cc.getDeclaredMethod(method);
			return getMethodParamNames(cm);
		} catch (Exception e) {
			throw new ParamFoundException(clazz.getName()+"."+method);
		}
	}

	/**
	 * 通过指定方法找到对应的参数名称列表
	 * 
	 * @param cm
	 * @return
	 * @throws NotFoundException
	 * @throws NotFoundException
	 */
	private static String[] getMethodParamNames(CtMethod cm)
			throws NotFoundException {
		MethodInfo methodInfo = cm.getMethodInfo();
		CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
		LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute
				.getAttribute(LocalVariableAttribute.tag);
		if (attr == null) {
			logger.error(String.format(msg, cm.getDeclaringClass().getName()));
			//return new String[0];20141006
			return null;
		}

		String[] paramNames = new String[cm.getParameterTypes().length];
		int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
		for (int i = 0; i < paramNames.length; i++) {
			paramNames[i] = attr.variableName(i + pos);
		}
		return paramNames;
	}

	public static String[] getMethodParamNames(Method method) {
		Parameter[] parameters = method.getParameters();
		String[] parameterNames = new String[parameters.length];
		for (int i = 0; i < parameters.length; i++) {
			Parameter param = parameters[i];
			if (!param.isNamePresent()) {
				logger.error(String.format(msg, method.getDeclaringClass().getName()));
				return null;
			}
			parameterNames[i] = param.getName();
		}
		return parameterNames;
	}
}
